﻿using log4net;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using Timesheet.Data.Infrastructure;
using Timesheet.Data.Repository;
using Timesheet.Domain;

namespace Timesheet.Service
{
    public class ProjectService : IProjectService
    {
        private readonly IProjectRepository _ProjRepository;
        private readonly IUnitOfWork _UnitOfWork;
        private readonly IUserRepository _UserRepository;
        private readonly IPrjReferencesRepository _PrjReferencesRepository;
        private readonly ITeamRepository _TeamRepository;
        private readonly ITeamDetailRepository _TeamDetailRepository;
        private readonly ITimeSheetDetailsRepository _TimeSheetDetailsRepository;
        private readonly ITimeSheetsRepository _TimeSheetRepository;
        private readonly IClassCodeRepository _ClassCodeRepository;
        private readonly ITimeSheetDetailsNoteRepository _NoteRepository;
        private readonly ITeamService _TeamService;
        public ILog Logger { get; private set; }

        public ProjectService(ITimeSheetsRepository timeSheetRepository, IClassCodeRepository classCodeRepository, ITimeSheetDetailsRepository timeSheetDetailsRepository, IProjectRepository projectRepository, IUserRepository userRepository, ITeamRepository teamRepository, IPrjReferencesRepository prjReferencesRepository,
            ITeamDetailRepository teamDetailRepository, ITimeSheetDetailsNoteRepository timeSheetDetailsNoteRepository,ITeamService teamService, IUnitOfWork unitOfWork)
        {
            this._ProjRepository = projectRepository;
            this._UnitOfWork = unitOfWork;
            this._UserRepository = userRepository;
            this._PrjReferencesRepository = prjReferencesRepository;
            this._TeamRepository = teamRepository;
            this._TeamDetailRepository = teamDetailRepository;
            this._TimeSheetDetailsRepository = timeSheetDetailsRepository;
            this._ClassCodeRepository = classCodeRepository;
            this._TimeSheetRepository = timeSheetRepository;
            this._NoteRepository = timeSheetDetailsNoteRepository;
            this._TeamService = teamService;
        }


        #region IProjectService Members
        //public IList<Project> GetProjects(long userID)
        //{
        //    UserRepository userRes = new UserRepository(_UnitOfWork);
        //    userRes.GetQuery().Where(x=>x.Id==userID)
        //    return _ProjRepository;
        //}
        public IList<Project> GetProjects()
        {
            return _ProjRepository.GetAll().ToList();
        }

        public IList<Project> GetAllProjects(long userID)
        {
            return _ProjRepository.GetAll().ToList();
        }

        public bool CheckExist(Project entity)
        {
            throw new NotImplementedException();
        }

        public Project GetByID(Int64 id)
        {
            return _ProjRepository.GetById(id);
        }

        public void Add(Project entity)
        {
            _ProjRepository.Add(entity);
        }

        public void Update(Project entity)
        {
            _ProjRepository.Update(entity);
        }

        public void SimpleUpdate(Project entity)
        {
            Project domain = _ProjRepository.GetById(entity.PrjID);
            domain.ProjectName = entity.ProjectName;
            domain.CustomerInfo = entity.CustomerInfo;
            domain.Active = entity.Active;
            _ProjRepository.Update(domain);
        }

        public void Delete(Project entity)
        {
            _ProjRepository.Delete(entity);

        }

        public T ToEntity<T>(OrderedDictionary value, string key, bool isUpdate) where T : class
        {
            T result = default(T);
            if (isUpdate)
            {
                int keyvalue = (int)value[key];
                result = GetByID(keyvalue) as T;
            }
            else
            {
                result = (T)Activator.CreateInstance(typeof(T));
            }
            foreach (string item in value.Keys)
            {
                if (isUpdate && item == key)
                    continue;
                var pro = result.GetType().GetProperty(item);
                if (pro != null)
                {
                    object val = value[item];
                    pro.SetValue(result, val, null);
                }
            }
            return result;
        }

        public IList<Project> GetProjects(long userID)
        {
            var user = _UserRepository.GetQuery().FirstOrDefault(x => x.Id == userID);
            if (user == null)
                return null;
            IList<Project> result = new List<Project>();


            var lstMgrPrj = _ProjRepository.GetAll().Where(x => x.CreateBy == userID).Distinct().ToList();

            if (lstMgrPrj != null && lstMgrPrj.Count > 0)
                result = result.Union(lstMgrPrj).ToList();



            //if(user.Coordinator)
            //{
            var refQuery = _PrjReferencesRepository.GetQuery().Where(x => x.RefID == user.Id);
            var q = _ProjRepository.GetQuery()
                                  .Where(x => x.Active && refQuery.Any(r => r.ProjID == x.PrjID));

            var lstCoordPrj = q.Distinct().ToList();

            if (lstCoordPrj != null && lstCoordPrj.Count > 0)
                result = result.Union(lstCoordPrj).ToList();
            //}


            //if (user.TeamLead)
            //{
            var qTeamDetail = _TeamDetailRepository.GetQuery().Where(x => x.EmployerID == userID);
            var qTeam = _TeamRepository.GetQuery().Where(x => qTeamDetail.Any(t => t.TeamID == x.Id));
            var qPrj = _ProjRepository.GetAll().Where(x => qTeam.Any(t => t.ProjectID == x.PrjID));
            var lstLeadPrj = qPrj.Distinct().ToList();

            if (lstLeadPrj != null && lstLeadPrj.Count > 0)
                result = result.Union(lstLeadPrj).ToList();
            //}
            return result.Distinct().ToList();
        }


        public IList<Project> GetActivedRefProjects(long userID)
        {
            return GetRefProjects(userID).Where(u => u.Active == true).ToList();
        }

        public IList<Project> GetRefProjects(long userID)
        {
            var user = _UserRepository.GetQuery().FirstOrDefault(x => x.Id == userID);
            if (user == null)
                return null;
            IList<Project> result = new List<Project>();


            if (user.Manager)
            {
                var lstMgrPrj = _ProjRepository.GetAll().Distinct().ToList();

                if (lstMgrPrj != null && lstMgrPrj.Count > 0)
                    result = result.Union(lstMgrPrj).ToList();
            }

            if (user.Coordinator)
            {
                var refQuery = _PrjReferencesRepository.GetQuery().Where(x => x.RefID == user.Id && x.Active && x.Type == "2");
                var q = _ProjRepository.GetQuery()
                                      .Where(x => x.Active && refQuery.Any(r => r.ProjID == x.PrjID));

                var lstCoordPrj = q.Distinct().ToList();

                if (lstCoordPrj != null && lstCoordPrj.Count > 0)
                    result = result.Union(lstCoordPrj).ToList();
            }


            if (user.TeamLead)
            {
                var qTeamDetail = _TeamDetailRepository.GetQuery().Where(x => x.EmployerID == userID);
                var qTeam = _TeamRepository.GetQuery().Where(x => qTeamDetail.Any(t => t.TeamID == x.Id));
                var qPrj = _ProjRepository.GetAll().Where(x => qTeam.Any(t => t.ProjectID == x.PrjID));
                var lstLeadPrj = qPrj.Distinct().ToList();

                if (lstLeadPrj != null && lstLeadPrj.Count > 0)
                    result = result.Union(lstLeadPrj).ToList();
            }
            return result.Distinct().ToList();
        }

        public IList<Project> GetProjectsByStatusAndUserId(string role, long userID)// anh ko co xai role
        {
            User user = _UserRepository.GetById(userID);
            if (user.Manager == true)
            {
                //Lay 
                return _ProjRepository.GetQuery().Where(p => p.CreateBy == userID).ToList();
            }
            else if (user.Coordinator == true)
            {
                IList<long> projectIds = _PrjReferencesRepository.GetQuery()
                    .Where(p => p.Active == true && p.Type == "2")
                    .Select(p => p.ProjID).Distinct().ToList();
                return _ProjRepository.GetQuery().Where(p => projectIds.Contains(p.PrjID)).ToList();
            }
            else
            {
                return new List<Project>();
            }

        }

        #endregion

        #region IProjectService Members


        public bool checkOwnerProject(long userId, long projectId)
        {
            Project project = _ProjRepository.GetById(projectId);
            if (project == null)
                throw new Exception();
            if (project.CreateBy == userId)
                return true;
            return false;
        }

        #endregion

        #region IProjectService Members


        public IList<object> GetReportData(long prjID)
        {
            List<object> result = new List<object>();
            rptProject prj = new rptProject();
            List<rptTimeSheetDetails> tmshData = new List<rptTimeSheetDetails>();

            var project = _ProjRepository.GetById(prjID);
            if (project != null)
            {
                prj.Contact = project.Contact;
                prj.CustomerInfo = project.CustomerInfo;
                prj.JobDes = project.JobDes;
                prj.JobInfo = project.JobInfo;
                prj.NetCode = project.NetCode;
                prj.ProjectName = project.ProjectName;
                prj.ResponsePerson = project.ResponsePerson;
                prj.Ticket = project.Ticket;
                prj.Wbs = project.Wbs;
                var locations = _PrjReferencesRepository.GetQuery().Where(x => x.Type == "1" && x.ProjID == prjID).Select(i => i.RefNames).ToList();
                prj.Locations = string.Join(";", locations);
            }
            try
            {
                var TimeSheet = _TimeSheetRepository.GetQuery().Where(x => x.ProjectID == prjID);
                var tmshDetail = _TimeSheetDetailsRepository.GetQuery().Where(x => TimeSheet.Any(y => y.Id == x.TransID)).ToList();
                if (tmshDetail != null)
                {
                   
                    foreach (var item in tmshDetail)
                    {
                        rptTimeSheetDetails tsmh = new rptTimeSheetDetails();

                        var classCode = _ClassCodeRepository.GetQuery().Where(x => x.Id == item.ClassCode).FirstOrDefault();
                        tsmh.ClassCode = classCode == null ? "" : classCode.Name;
                        tsmh.Extension = item.Extension;
                        var employ = _UserRepository.GetById(item.EmployerID);
                        tsmh.FullName = employ == null ? "" : employ.FullName;
                        tsmh.Mileage = item.Mileage;
                        tsmh.PerDiemFull = item.PerDiemFull;
                        tsmh.PerDiemMeals = item.PerDiemMeals;
                        tsmh.Notes = item.Notes;
                        tsmh.SunOTHours = item.SunOTHours;
                        tsmh.SunSTHours = item.SunSTHours;
                        tsmh.MonOTHours = item.MonOTHours;
                        tsmh.MonSTHours = item.MonSTHours;
                        tsmh.TueOTHours = item.TueOTHours;
                        tsmh.TueSTHours = item.TueSTHours;
                        tsmh.WebOTHours = item.WebOTHours;
                        tsmh.WebSTHours = item.WebSTHours;
                        tsmh.ThuOTHours = item.ThuOTHours;
                        tsmh.ThuSTHours = item.ThuSTHours;
                        tsmh.FirOTHours = item.FirOTHours;
                        tsmh.FriSTHours = item.FriSTHours;
                        tsmh.SatOTHours = item.SatOTHours;
                        tsmh.SatSTHours = item.SatSTHours;
                        tsmh.TotalOT = item.SunOTHours + item.MonOTHours + item.TueOTHours + item.WebOTHours + item.ThuOTHours + item.FirOTHours + item.SatOTHours;
                        tsmh.TotalST = item.SunSTHours + item.MonSTHours + item.TueSTHours + item.WebSTHours + item.ThuSTHours + item.FriSTHours + item.SatSTHours;
                        tmshData.Add(tsmh);
                    }
                }
            }
            catch (Exception e)
            {

            }
            result.Add(prj);
            result.Add(tmshData);
            return result;
        }

        public IList<object> GetReportData(long prjID, long tmshID)
        {
            List<object> result = new List<object>();
            rptProject prj = new rptProject();
            List<rptTimeSheetDetails> tmshData = new List<rptTimeSheetDetails>();

            var project = _ProjRepository.GetById(prjID);
            if (project != null)
            {
                prj.Contact = project.Contact;
                prj.CustomerInfo = project.CustomerInfo;
                prj.JobDes = project.JobDes;
                prj.JobInfo = project.JobInfo;
                prj.NetCode = project.NetCode;
                prj.ProjectName = project.ProjectName;
                prj.ResponsePerson = project.ResponsePerson;
                prj.Ticket = project.Ticket;
                prj.Wbs = project.Wbs;
                var locations = _PrjReferencesRepository.GetQuery().Where(x => x.Type == "1" && x.ProjID == prjID).Select(i => i.RefNames).ToList();
                prj.Locations = string.Join(";", locations);
            }
            try
            {
                var tmshDetail = _TimeSheetDetailsRepository.GetQuery().Where(x => x.TransID == tmshID).ToList();
                var timesheet = _TimeSheetRepository.GetByID(tmshID);
                Team team = _TeamService.GetByID(timesheet.TeamID);
                prj.TeamName = team.TeamName;
                if (tmshDetail != null)
                {
                    foreach (var item in tmshDetail)
                    {
                        rptTimeSheetDetails tsmh = new rptTimeSheetDetails();
                        var classCode = _ClassCodeRepository.GetQuery().Where(x => x.Id == item.ClassCode).FirstOrDefault();
                        tsmh.ClassCode = classCode == null ? "" : classCode.Name;
                        tsmh.Extension = item.Extension;
                        var employ = _UserRepository.GetById(item.EmployerID);
                        tsmh.FullName = employ == null ? "" : employ.FullName;
                        tsmh.Mileage = item.Mileage;
                        tsmh.PerDiemFull = item.PerDiemFull;
                        tsmh.PerDiemMeals = item.PerDiemMeals;
                        tsmh.Notes = item.Notes;
                        tsmh.SunOTHours = item.SunOTHours;
                        tsmh.SunSTHours = item.SunSTHours;
                        tsmh.MonOTHours = item.MonOTHours;
                        tsmh.MonSTHours = item.MonSTHours;
                        tsmh.TueOTHours = item.TueOTHours;
                        tsmh.TueSTHours = item.TueSTHours;
                        tsmh.WebOTHours = item.WebOTHours;
                        tsmh.WebSTHours = item.WebSTHours;
                        tsmh.ThuOTHours = item.ThuOTHours;
                        tsmh.ThuSTHours = item.ThuSTHours;
                        tsmh.FirOTHours = item.FirOTHours;
                        tsmh.FriSTHours = item.FriSTHours;
                        tsmh.SatOTHours = item.SatOTHours;
                        tsmh.SatSTHours = item.SatSTHours;
                        tsmh.TotalOT = item.SunOTHours + item.MonOTHours + item.TueOTHours + item.WebOTHours + item.ThuOTHours + item.FirOTHours + item.SatOTHours;
                        tsmh.TotalST = item.SunSTHours + item.MonSTHours + item.TueSTHours + item.WebSTHours + item.ThuSTHours + item.FriSTHours + item.SatSTHours;
                        List<TimeSheetDetailsNote> notes = _NoteRepository.GetQuery().Where(p => p.TimeSheetDetailsId == item.Id).ToList();
                        if (notes != null && notes.Count > 0)
                        {
                            tsmh.Notes = notes[0].Notes;
                            tsmh.Note1 = notes[0].Note1;
                            tsmh.Note2 = notes[0].Note2;
                            tsmh.Note3 = notes[0].Note3;
                            tsmh.Note4 = notes[0].Note4;
                            tsmh.Note5 = notes[0].Note5;
                            tsmh.Note6 = notes[0].Note6;
                            tsmh.Note7 = notes[0].Note7;
                        }
                        tmshData.Add(tsmh);
                    }
                }
            }
            catch (Exception e)
            {

            }
            result.Add(prj);
            result.Add(tmshData);
            return result;
        }


        #endregion
    }
}
